package com.example.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mall.constants.BaseConstants;
import com.example.mall.domain.PayFlow;
import com.example.mall.domain.PayOrder;
import com.example.mall.dto.AlipayNotifyDto;
import com.example.mall.dto.NotifyDto;
import com.example.mall.dto.PayFlowDto;
import com.example.mall.mapper.PayFlowMapper;
import com.example.mall.query.PageDTO;
import com.example.mall.query.PayFlowQuery;
import com.example.mall.service.IPayFlowService;

import com.example.mall.service.IPayOrderService;
import com.example.mall.util.AssertUtil;
import com.example.mall.util.CodeGenerateUtils;
import com.example.mall.util.CopyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 支付流水表 服务实现类
 * </p>
 *
 * @author whale
 * @since 2025-06-03
 */
@Service
@Slf4j
public class PayFlowServiceImpl extends ServiceImpl<PayFlowMapper, PayFlow> implements IPayFlowService {

    @Autowired
    private PayFlowMapper payFlowMapper;
    @Autowired
    private IPayOrderService payOrderService;

    @Override
    public PageDTO<PayFlowDto> queryPage(PayFlowQuery payFlowQuery) {
        if (payFlowQuery == null) {
            payFlowQuery = new PayFlowQuery();
        }
        Page<PayFlow> page = payFlowQuery.toMpPageByDefaultCreateTimeAsc();
        Page<PayFlow> cartPage = lambdaQuery()
                .like(payFlowQuery.getId()!= null, PayFlow::getId, payFlowQuery.getId())
                .like(payFlowQuery.getSubject()!= null, PayFlow::getSubject, payFlowQuery.getSubject())
                .like(payFlowQuery.getOutTradeNo()!= null, PayFlow::getOutTradeNo, payFlowQuery.getOutTradeNo())
                .like(payFlowQuery.getTotalAmount()!= null, PayFlow::getTotalAmount, payFlowQuery.getTotalAmount())
                .like(payFlowQuery.getTradeStatus()!= null, PayFlow::getTradeStatus, payFlowQuery.getTradeStatus())
                .like(payFlowQuery.getCode()!= null, PayFlow::getCode, payFlowQuery.getCode())
                .like(payFlowQuery.getMsg()!= null, PayFlow::getMsg, payFlowQuery.getMsg())
                .like(payFlowQuery.getPaySuccess()!= null, PayFlow::getPaySuccess, payFlowQuery.getPaySuccess())
                .like(payFlowQuery.getPassbackParams()!= null, PayFlow::getPassbackParams, payFlowQuery.getPassbackParams())
                .apply(payFlowQuery.getNotifyTime() != null,
                        "DATE_FORMAT(notify_time, '%Y-%m-%d') = DATE_FORMAT({0}, '%Y-%m-%d')",
                        payFlowQuery.getNotifyTime())
                .orderByDesc(PayFlow::getNotifyTime)
                .page(page);
        return PageDTO.of(cartPage, PayFlowDto.class);
    }

    @Override
    public PayFlow queryPayFlowById(Long id) {
        AssertUtil.isNotNull(id, "id不能为空");
        return payFlowMapper.selectById(id);
    }

    @Override
    public List<PayFlow> queryPayFlowList() {
        return this.list();
    }

    @Override
    public void insert(PayFlowDto payFlowDto) {
        PayFlow payFlow = new PayFlow();
        CopyUtils.copyProperties(payFlowDto, payFlow);
        payFlow.setId(CodeGenerateUtils.generateUniqueId());
        payFlowMapper.insert(payFlow);
    }

    @Override
    public void update(PayFlowDto payFlowDto) {
        AssertUtil.isNotNull(payFlowDto.getId(), "id不能为空");
        PayFlow payFlow = payFlowMapper.selectById(payFlowDto.getId());
        AssertUtil.isNotNull(payFlow, "支付流水不存在");
        CopyUtils.copyProperties(payFlowDto, payFlow);
        payFlowMapper.updateById(payFlow);
    }

    @Override
    public void delete(Long id) {
        AssertUtil.isNotNull(id, "id不能为空");
        PayFlow payFlow = payFlowMapper.selectById(id);
        AssertUtil.isNotNull(payFlow, "支付流水不存在");
        payFlowMapper.deleteById(id);
    }

    @Override
    public void deleteBatch(List<Long> ids) {
        AssertUtil.isNotNull(ids, "id不能为空");
        List<PayFlow> payFlows = payFlowMapper.selectBatchIds(ids);
        AssertUtil.isNotNull(payFlows, "支付流水不存在");
        payFlowMapper.deleteBatchIds(ids);
    }

    @Override
    public PayFlow create(NotifyDto dto) {
        AlipayNotifyDto alipayNotifyDto = (AlipayNotifyDto) dto;
        PayFlow payFlow = new PayFlow();
        payFlow.setCode(alipayNotifyDto.getCode());
        payFlow.setMsg(alipayNotifyDto.getMsg());
        payFlow.setNotifyTime(new Date());
        payFlow.setOutTradeNo(alipayNotifyDto.getOut_trade_no());
        payFlow.setSubject(alipayNotifyDto.getSubject());
        payFlow.setTotalAmount(new BigDecimal(alipayNotifyDto.getTotal_amount()));
        payFlow.setTradeStatus(alipayNotifyDto.getTrade_status());
        payFlow.setPaySuccess(alipayNotifyDto.isTradeSuccess()==true?1:0);
        payFlow.setPassbackParams(alipayNotifyDto.getPassback_params());
        int insert = payFlowMapper.insert(payFlow);
        AssertUtil.isTrue(insert>0,"支付流水保存失败");

        //修改支付单状态
        PayOrder payOrder = payOrderService.selectByOrderNo(alipayNotifyDto.getOut_trade_no());
        payOrder.setPayStatus(alipayNotifyDto.isTradeSuccess()? BaseConstants.Pay.STATUS_SUCCESS:BaseConstants.Pay.STATUS_FAIL);
        AssertUtil.isTrue(payOrderService.updateById(payOrder),"支付流水保存失败");
        log.info("保存支付流水{}",payFlow);
        log.info("修改支付单状态{}",payOrder);
        return payFlow;
    }

    @Override
    public PayFlow selectByOutTradeNo(String outTradeNo) {
        AssertUtil.isNotNull(outTradeNo, "outTradeNo不能为空");
        LambdaQueryWrapper<PayFlow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PayFlow::getOutTradeNo, outTradeNo);
        return payFlowMapper.selectOne(queryWrapper);
    }
}
